import axios, {AxiosRequestConfig} from 'axios'
import {RestConfigType} from './RestConfigType'
import {LSKeys, LSMethods} from '../storage'
import {IResponse} from './IResponse'
import {ResponseError} from '../../api/ResponseError'

const ERROR_MESSAGE_DEFAULT = 'Произошла неизвестная ошибка. Обратитесь в службу поддержки.'

function getToken(): any {
  //TODO:: TokenDto
  return LSMethods.getStorageData(LSKeys.TOKEN, null)
}

function getAuthorizationHeader() {
  let token: any = getToken() //TODO:: TokenDto
  // return token ? {Authorization: 'Bearer ' + token.accessToken} : {}
  return {}
}

function getHeaders() {
  const authorizationHeader: any = getAuthorizationHeader()
  return Object.assign({'Content-Type': 'application/json'}, authorizationHeader)
}

async function handleRequest(
  url: string,
  options: AxiosRequestConfig,
  onError: (error: ResponseError) => void,
): Promise<any> {
  try {
    const headers = Object.assign(getHeaders(), options.headers || {})
    // console.log('headers', headers)
    const config: AxiosRequestConfig = {
      url: url,
      ...options,
      headers: {
        ...headers,
        'Content-Type': 'application/json',
        // 'Cache-Control': 'no-cache',
      },
    }
    const response = await axios.request(config)
    if (response.status >= 200 && response.status < 300) {
      return response.data
    } else {
      let error: ResponseError = new ResponseError(response.status, response.data?.errorMessage)
      if (!error.errorMessage) {
        error.errorMessage = ERROR_MESSAGE_DEFAULT
      }
      if (onError) {
        onError(error)
      } else {
        throw error
      }
    }
  } catch (e: any) {
    let err
    if (e.status && e.errorMessage) {
      err = e
    } else {
      err = new ResponseError(500, ERROR_MESSAGE_DEFAULT)
    }

    throw err
  }
}

async function apiGet(
  url: string,
  restConfig: RestConfigType,
  onError?: (error: ResponseError) => void,
): Promise<IResponse | any> {
  const {options = null, headers = null} = restConfig
  let urlObject = new URL(url)
  if (options) {
    for (let param in options) {
      urlObject.searchParams.append(param, options[param])
    }
  }

  const config: AxiosRequestConfig = {
    method: 'GET',
    headers: headers || {},
    timeout: 10000,
  }

  return await handleRequest(urlObject.toString(), config, onError)
}

async function apiPost(
  url: string,
  data: any,
  restConfig: RestConfigType,
  onError?: (error: ResponseError) => void,
): Promise<IResponse> {
  const {options = null, timeout = null} = restConfig
  let urlObject = new URL(url)
  if (options) {
    for (let param in options) {
      urlObject.searchParams.append(param, options[param])
    }
  }

  const config: AxiosRequestConfig = {
    method: 'POST',
    data: JSON.stringify(data),
    timeout: timeout || 10000,
  }

  return await handleRequest(urlObject.toString(), config, onError)
}

async function apiPostFile(
  url: string,
  formData: any,
  restConfig: RestConfigType,
  onError?: (error: ResponseError) => void,
): Promise<any> {
  const {options = null, timeout = null} = restConfig
  let urlObject = new URL(url)
  if (options) {
    for (let param in options) {
      urlObject.searchParams.append(param, options[param])
    }
  }
  const config: AxiosRequestConfig = {
    method: 'POST',
    data: formData,
    timeout: timeout || 10000,
    ...options,
  }
  return handleRequest(url, config, onError)
}

export {apiGet, apiPost, apiPostFile}
